﻿#pragma once
#include<d3d12.h>
#include"PreStd.h"
namespace Bonnie {
    class DescriptorHeapAllocation
    {
    public:
        // Creates null allocation
        DescriptorHeapAllocation();

        // Initializes non-null allocation 
        DescriptorHeapAllocation(ID3D12DescriptorHeap* pHeap,
            D3D12_CPU_DESCRIPTOR_HANDLE CpuHandle,
            D3D12_GPU_DESCRIPTOR_HANDLE GpuHandle,
            uint32_t NHandles,
            uint16_t AllocationManagerId);

        // Move constructor (copy is not allowed)
        DescriptorHeapAllocation(DescriptorHeapAllocation&& Allocation);

        // Move assignment (assignment is not allowed)
        DescriptorHeapAllocation& operator = (DescriptorHeapAllocation&& Allocation);

        // Destructor automatically releases this allocation through the allocator
        ~DescriptorHeapAllocation()
        {
            
        }

        // Returns CPU descriptor handle at the specified offset
        D3D12_CPU_DESCRIPTOR_HANDLE GetCpuHandle(uint32_t Offset = 0) const
        {
            D3D12_CPU_DESCRIPTOR_HANDLE CPUHandle = m_FirstCpuHandle;
            if (Offset != 0)
                CPUHandle.ptr += m_DescriptorSize * Offset;
            return CPUHandle;
        }

        // Returns GPU descriptor handle at the specified offset
        D3D12_GPU_DESCRIPTOR_HANDLE GetGpuHandle(uint32_t Offset = 0) const
        {
            D3D12_GPU_DESCRIPTOR_HANDLE GPUHandle = m_FirstGpuHandle;
            if (Offset != 0)
                GPUHandle.ptr += m_DescriptorSize * Offset;
            return GPUHandle;
        }

        // Returns pointer to the descriptor heap that contains this allocation
        ID3D12DescriptorHeap* GetDescriptorHeap() { return m_pDescriptorHeap; }

        size_t GetNumHandles()const { return m_NumHandles; }

        bool IsNull() const { return m_FirstCpuHandle.ptr == 0; }
        bool IsShaderVisible() const { return m_FirstGpuHandle.ptr != 0; }
        size_t GetAllocationManagerId() { return m_AllocationManagerId; }
        UINT GetDescriptorSize()const { return m_DescriptorSize; }

    private:
        // No copies, only moves are allowed
        DescriptorHeapAllocation(const DescriptorHeapAllocation&) = delete;
        DescriptorHeapAllocation& operator= (const DescriptorHeapAllocation&) = delete;

        // First CPU descriptor handle in this allocation
        D3D12_CPU_DESCRIPTOR_HANDLE m_FirstCpuHandle = { 0 };

        // First GPU descriptor handle in this allocation
        D3D12_GPU_DESCRIPTOR_HANDLE m_FirstGpuHandle = { 0 };

        // Pointer to the D3D12 descriptor heap that contains descriptors in this allocation
        ID3D12DescriptorHeap* m_pDescriptorHeap = nullptr;

        // Number of descriptors in the allocation
        uint32_t m_NumHandles = 0;

        // Allocation manager ID
        uint16_t m_AllocationManagerId = static_cast<uint16_t>(-1);

        // Descriptor size 
        uint16_t m_DescriptorSize = 0;
    };

}
